package base

import (
	"github.com/spf13/cobra"
	"log"
	"os"
	"reflect"
	"strconv"
	"strings"
)

// ParseExecute value 自定义的结构体指针
func ParseExecute(value interface{}, cmd *cobra.Command) {
	at := reflect.TypeOf(value)
	if strings.Contains(at.String(), "*") {
		at = at.Elem()
	}
	vt := reflect.ValueOf(value).Elem()
	num := at.NumField()
	unreadyVal := map[string]any{}

	for i := 0; i < num; i++ {
		fd := at.Field(i)
		name := fd.Tag.Get("name")
		shorthand := fd.Tag.Get("shorthand")
		desc := fd.Tag.Get("desc")
		defaultValue := fd.Tag.Get("default")

		typeStr := fd.Type.Name()
		switch typeStr {
		case "string":
			var str string
			cmd.Flags().StringVarP(&str, name, shorthand, defaultValue, desc)
			unreadyVal[fd.Name] = &str
		case "int":
			var it int
			di, _ := strconv.Atoi(defaultValue)
			cmd.Flags().IntVarP(&it, name, shorthand, di, desc)
			unreadyVal[fd.Name] = &it
		case "bool":
			var it bool
			di := defaultValue == "true"
			cmd.Flags().BoolVarP(&it, name, shorthand, di, desc)
			unreadyVal[fd.Name] = &it
		default:
			continue
		}
	}

	cmd.PreRun = func(cmd *cobra.Command, args []string) {
		for k, v := range unreadyVal {
			fd := vt.FieldByName(k)
			typeStr := fd.Type().Name()
			switch typeStr {
			case "string":
				strPrt, ok := v.(*string)
				if ok {
					fd.SetString(*strPrt)
				}
			case "int":
				it, ok := v.(*int)
				if ok {
					fd.SetInt(int64(*it))
				}
			case "bool":
				it, ok := v.(*bool)
				if ok {
					fd.SetBool(*it)
				}
			default:
				continue
			}
		}
	}
	err := cmd.Execute()
	if err != nil {
		log.Fatalln("cmd execute error: ",err)
		os.Exit(1)
	}
}
